﻿#include "System.h"
#include "Device/PhoneDevice.h"

#include "Port/UDP.h"
#include <unistd.h>
#include <linux/serial.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "Log.h"
System* System::m_pInstance = NULL;
QMutex System::m_Mutex;

System::System(QObject *parent) :
    QObject(parent)
{
    m_second = 0;
    m_KNXMac = 0xffffffff;
    m_globalStatus = 0;
    detectIPTimer = new QTimer(this);
    detectIPTimer ->setInterval(500);
    connect(detectIPTimer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
    detectIPTimer ->start();

    watchdogTimer = new QTimer(this);
    watchdogTimer ->setInterval(1000);
    connect(watchdogTimer, SIGNAL(timeout()), this, SLOT(watchdogSlot()));
    watchdogTimer ->start();


    checkLogFileTimer = new QTimer(this);
    checkLogFileTimer ->setInterval(1000*30);
    connect(checkLogFileTimer, SIGNAL(timeout()), this, SLOT(checkLogFileSlot()));
    checkLogFileTimer ->start();

    m_watchdogIOState = false;

#ifdef SSD202
      fd=open("/dev/watchDog-gpio",O_RDWR);
      if(fd > 0)
      {
          watchdogTimer ->start();
      }
//    system("echo 166 > /sys/class/gpio/export");
//    system("echo out > /sys/class/gpio/gpio166/direction");
#else

    system("echo 166 > /sys/class/gpio/export");
    system("echo out > /sys/class/gpio/gpio166/direction");

#endif
}


QString System::appVersion()
{
#ifdef SSD202
    QString appVersion = "1.6.2.36";
#else
    QString appVersion = "2.2.36";
 #endif
    return appVersion;
}

QString System::appDirPath()
{
    return QCoreApplication::applicationDirPath();
}

QString System::appFilePath()
{
    return QCoreApplication::applicationFilePath();
}


QString System::rootPath()
{
    QString rootPath;
#ifdef Q_OS_WIN
    rootPath = "C:/GateWay";
#endif
#ifdef Q_OS_LINUX
    rootPath = "/root";
#endif
    return rootPath;
}

QByteArray System::timeBCD()
{
    QDateTime time(QDateTime::currentDateTime());
    QString systemTime = time.toString("yyyy,MM,dd,hh,mm,ss").insert(2,",");
    QStringList strList = systemTime.split(",");
    QByteArray timeBCD;
    for(int i=0; i<strList.count(); i++)
    {
        quint8 temp = strList.at(i).toInt()%10+strList.at(i).toInt()/10*16;

        timeBCD.append(temp);
    }
    return timeBCD;
}

void System::setTimeBCD(const QByteArray &timeBCD)
{
    if(timeBCD.size() != 7)
    {
        return;
    }

    QString time;
    time += QString::number(timeBCD.at(0),16);
    time += QString::number(timeBCD.at(1),16);
    time += "-";
    time += QString::number(timeBCD.at(2),16);
    time += "-";
    time += QString::number(timeBCD.at(3),16);
    time += " ";
    time += QString::number(timeBCD.at(4),16);
    time += ":";
    time += QString::number(timeBCD.at(5),16);
    time += ":";
    time += QString::number(timeBCD.at(6),16);
    std::string strTime="date -s \"\"";
    strTime.insert(9,time.toStdString());

#ifdef Q_OS_LINUX
    system(strTime.c_str());
    system("hwclock --systohc");   
#endif
}

QString System::ip()
{
    QString ip;
#ifdef Q_OS_LINUX
    QNetworkInterface netWorkInterface = QNetworkInterface::interfaceFromName("eth0");
    QList<QNetworkAddressEntry> netList = netWorkInterface.addressEntries();
   // PhoneDevice a;
    for(int i=0; i<netList.size(); i++)
    {
        QNetworkAddressEntry net = netList.at(i);
        if(net.ip().protocol() == QAbstractSocket::IPv4Protocol)
        {
            if(net.ip().toString() != "127.0.0.1")
            {
                ip = net.ip().toString();
                break;
            }
        }
    }
#endif

    return ip;
}

void System::timeoutSlot()
{
    QString ip = System::ip();

    if(!ip.isNull())
    {
        CloudProtocol tocol;
        Package package;
        QByteArray databody;
        databody.append((char)0x00);
        databody.append(deviceType());
        databody.append((char)0x00);
        databody.append(0x01);
        databody.append((char)0);
        databody.append((char)0);
        databody.append((char)0);
        databody.append((char)0);
        MacXml *macXml = MacXml::getInstance();
        QString mac = macXml->mac();
        char*  ch;
        QByteArray ba = mac.toLatin1(); // must
        ch=ba.data();
        databody.append(ch);
        package.setFunction(0x34);
        package.setBody(databody);
        package.setLength(2);
        PortStruct target;
        {
        target.setType("UDP");
        target.setName("NetPointDeviceUDP");
        target.setIp("255.255.255.255");
        target.setPort(20000);
        }
        QByteArray data=tocol.generateData(package);
        qDebug()<<"get IP="<<ip;
        UDP udp;
        udp.write(target,data);
        detectIPTimer->stop();
        emit detectedIpSignal();
    }
}

void System::checkLogFileSlot()
{
    Log::removeOutOfDate();
}
#ifdef SSD202
void System::watchdogSlot()
{
    static char high=1;
    static char low=0;
    m_second++;
    if(m_watchdogIOState)
    {
        m_watchdogIOState = false;
#ifdef Q_OS_LINUX
   //     system("echo 0 > /sys/class/gpio/gpio166/value");
        write(fd,&low,1);
#endif
    }
    else
    {
        m_watchdogIOState = true;
#ifdef Q_OS_LINUX
   //     system("echo 1 > /sys/class/gpio/gpio166/value");
        write(fd,&high,1);
#endif
    }
}
#else
void System::watchdogSlot()
{
    m_second++;
    if(m_watchdogIOState)
    {
        m_watchdogIOState = false;
#ifdef Q_OS_LINUX
        system("echo 0 > /sys/class/gpio/gpio166/value");
#endif
    }
    else
    {
        m_watchdogIOState = true;
#ifdef Q_OS_LINUX
        system("echo 1 > /sys/class/gpio/gpio166/value");
#endif
    }
}

#endif

QString System::ReadUuid()
{
    MI_U64 u64Uuid;
    QString GetUuid;

    MI_S32 s32Ret = MI_ERR_SYS_FAILED;

    s32Ret = MI_SYS_ReadUuid (&u64Uuid);

    if(!s32Ret)

    {
        qDebug()<<"uuid u64Uuid is:"<<u64Uuid;
        GetUuid=QString::number(u64Uuid);
        return GetUuid;
    }

    return 0;


}


NetParam System::netParam()
{
    NetParam netParam;


    LocalIni *localIni = LocalIni::getInstance();
    localIni->setPath(System::rootPath() + "/local.ini");
    if(localIni->parser())
    {
        quint8 mode = localIni->netParam().mode();
        netParam.setMode(mode);
    }
#ifdef Q_OS_LINUX
    QNetworkInterface netWorkInterface = QNetworkInterface::interfaceFromName("eth0");
    QList<QNetworkAddressEntry> netList = netWorkInterface.addressEntries();

    for(int i=0; i<netList.size(); i++)
    {
        QNetworkAddressEntry net = netList.at(i);
        if(net.ip().protocol() == QAbstractSocket::IPv4Protocol)
        {
            if(net.ip().toString() != "127.0.0.1")
            {
                netParam.setIp(net.ip().toString());
                netParam.setMask(net.netmask().toString());
                break;
            }
        }
    }

    FILE *fp = NULL;

    fp = fopen("/proc/net/route", "r");
    if(fp != NULL)
    {
        unsigned int tempDest = 0;
        unsigned int tempGateway = 0;
        char buff[256] = {0};
        char *p = NULL;

        while(fgets(buff, 255, fp))
        {
            p = strchr(buff, '\t');
            if(p == NULL)
            {
                continue;
            }
            p++;

            sscanf(p, "%X %X", &tempDest, &tempGateway);

            if((tempDest == 0) || (0 != tempGateway))
            {
                QString gateway;
                for(int i=0; i<4; i++)
                {
                    int temp = (tempGateway >> (i*8)) & 0xFF;
                    gateway += QString::number(temp,10)+".";
                }
                gateway.remove(gateway.size()-1,1);
                netParam.setGateway(gateway);
            }
        }
    }
    fclose(fp);
#endif

    return netParam;

}

bool System::setNetParam(const NetParam &netParam)
{
    LocalIni *localIni = LocalIni::getInstance();
    localIni->setPath(System::rootPath() + "/local.ini");
    bool isSuccess = localIni->modif(netParam);
    if(isSuccess)
    {
#ifdef Q_OS_LINUX
        QByteArray setIpPath = QString(System::rootPath() + "/setip.sh").toLatin1();
        system(setIpPath.data());
#endif
        return true;
    }
    else
    {
        return false;
    }

}

bool System::setTempNetParam(quint8 ipMode)
{
    if(ipMode == 0)
    {
        system("ifconfig eth0 192.168.120.2");
        return true;
    }
    if(ipMode == 1)
    {
        system("udhcpc -ieth0 &");
        return true;
    }
    return false;
}

quint32 System::totalRamSize()
{
    quint32 totalRamSize = 0;
#ifdef Q_OS_LINUX
    struct sysinfo s_info;
    sysinfo(&s_info);
    totalRamSize = s_info.totalram;
#endif
    return totalRamSize;
}

quint32 System::usedRamSize()
{
    quint32 usedRamSize = 0;
#ifdef Q_OS_LINUX
    struct sysinfo s_info;
    sysinfo(&s_info);
    usedRamSize = s_info.totalram - s_info.freeram;
#endif
    return usedRamSize;
}

quint64 System::totalFlashSize()
{
    quint64 tolalFlashSize = 0;
#ifdef Q_OS_LINUX
    struct statfs sfs;
    statfs("/", &sfs);
    tolalFlashSize = sfs.f_blocks*sfs.f_bsize;
#endif
    return tolalFlashSize;
}

quint64 System::usedFlashSize()
{
    quint64 usedFlashSize = 0;
#ifdef Q_OS_LINUX
    struct statfs sfs;
    statfs("/", &sfs);
    usedFlashSize = (sfs.f_blocks-sfs.f_bfree)*sfs.f_bsize;
#endif
    return usedFlashSize;
}

QString System::runningTime()
{
    QString runningTime;
    runningTime = QString::number(m_second/86400)+"天"
                + QString::number((m_second % 86400)/3600)+"小时"
                + QString::number((m_second % 3600 )/60)+"分";
    return runningTime;
}

void System::rebootSystem()
{
#ifdef Q_OS_LINUX
    system("sync");
    sleep(5);
    system("reboot");
#endif
}


QString System::systemName()
{
    QString systemName;
#ifdef Q_OS_WIN
    systemName = "Windows";
#endif

#ifdef Q_OS_LINUX
    systemName = "Linux";
#endif
    return systemName;
}
void System::readVersion()
{
    QString readData;
    QFile file("/dev/version");
    file.open(QFile::ReadOnly | QFile::Text);
    readData=file.read(16);
    qDebug()<<"readVersion="<<readData;
    file.close();

    QStringList list = readData.split(" ");


    m_Version=list.at(0);
    qDebug()<<"readVersion="<<m_Version;

}

void System::enableRS485()
{
#ifdef Q_OS_LINUX
    int fd = open("/dev/ttyS2",O_RDWR | O_NOCTTY);
   // qDebug()<<"!!!!!!!!!!!!!!!!!!!!!!=================================open ttyS2";
    if(fd != -1)
     {  // qDebug()<<"!!!!!!!!!!!!!!!!!!!!!!=================================FD!=-1";
        struct serial_rs485 rs485Config;
        memset(&rs485Config,0,sizeof(rs485Config));
        rs485Config.flags |= SER_RS485_ENABLED;
        rs485Config.flags |= SER_RS485_RTS_ON_SEND;
        rs485Config.delay_rts_after_send=1000;
        rs485Config.padding[0]=18;
        ioctl(fd,TIOCSRS485,&rs485Config);
      }
#endif
}

quint32 System::getKNXMac()
{
    return m_KNXMac;
}
void System::setKNXMac(quint32 mac)
{
    m_KNXMac = mac;
}

void System::setGlobalStatus(quint8 status)
{
    m_globalStatus = status;
}
quint8 System::getGlobalStatus()
{
    return m_globalStatus;
}


quint8 System::getKNXStatus()
{
    return m_kNXStatus;
}
void System::setKNXStatus(quint8 status)
{
    m_kNXStatus = status;
}

QString System::systemVersion()
{
//    QString systemVersion;
//#ifdef Q_OS_WIN
//    systemVersion = QString::number(QSysInfo::WindowsVersion);
//#endif

//#ifdef Q_OS_LINUX
//    systemVersion = "1.0.0";
//#endif
    return m_Version;
}

quint8 System::deviceType()
{
    quint8 type = 0;
    return type;
}



QMap<QString,QMetaObject> System::getDeviceMetaMap()
{
    return m_deviceMetaMap;
}
void System::setDeviceMetaMap(QMap<QString,QMetaObject> deviceMetaMap)
{
    m_deviceMetaMap = deviceMetaMap;
}

QMap<QString,BaseDevice*> System::getDeviceInstanceMap()
{
    return m_deviceInstanceMap;
}
void System::setDeviceInstanceMap(QMap<QString,BaseDevice*> deviceInstanceMap)
{
    m_deviceInstanceMap = deviceInstanceMap;
}



System::~System()
{

}
